<?php
/**
 * LilDate Engine
 * 
 * @copyright     Copyright 2011, Miha Nahtigal (http://www.nahtigal.com)
 * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
 * 
 * 
 * This LilDate behavior for CakePHP allows you to auto convert dates from local
 * format to default format suitable for saving into database
 * 
 */
class LilDateEngine {
/**
 * An array of settings
 */
    var $_settings = array();

/**
 * Instantiates object and its settings
 * 
 * @param array $settings Array of settings
 * @access public
 * @return void
 */
	public function __construct($settings = array()) {
		$settings = (array)$settings;
		
		$_defaults = array(
			'dateSeparator' => ($s = Configure::read('dateSeparator')) ? $s : '-',
			'dateFormat' => ($f = Configure::read('dateFormat')) ? $f : 'YMD'
		);
		
		$this->_settings = array_merge($_defaults, $settings);
	}
/**
 * Instantiate static instance
 * 
 * @param array $settings Array of scope properties
 * @access public
 * @return object
 */
	public static function getInstance($settings = array()) {
		static $instance = array();
		if (!$instance) {
			$instance = new LilDateEngine($settings);
		}
		return $instance;
	}
/**
 * Prevent object from clonning itself
 * 
 * @access protected
 * @return void
 */
	protected function __clone() { }
/**
 * Sets new date separator
 *
 * @param string $dateSeparator New date separator
 * @access public
 * @return void
 */
	function setDateSeparator($dateSeparator = null) {
		if (!empty($dateSeparator)) {
			$this->_settings['dateSeparator'] = $dateSeparator;
		}
	}
/**
 * Sets new date format
 *
 * @param string $dateFormat New date format (YMD, DMY,..)
 * @access public
 * @return void
 */
	function setDateFormat($dateFormat = null) {
		$this->_settings['dateFormat'] = $dateFormat;
	}
/**
 * decimalSeparator method
 *
 * @access public
 * @return string
 */
	function dateSeparator() {
		return $this->_settings['dateSeparator'];
	}
/**
 * dateFormat method
 *
 * @access public
 * @return string
 */
	function dateFormat() {
		return $this->_settings['dateFormat'];
	}
/**
 * Converts local date to general representation eg. YYYY-MM-DD
 * 
 * @param string $localDate Date in local format
 * @param array $options Options which can override default settings
 * @access public
 * @return string
 */
	function delocalize($localDate, $options = array()) {
		$settings = array_merge($this->_settings, (array)$options);
		$parts = explode($settings['dateSeparator'], $localDate);
		$order = array_flip(str_split($settings['dateFormat']));
		$ret = '';
		return implode('-', array($parts[$order['Y']], $parts[$order['M']], $parts[$order['D']]));
	}
/**
 * Returns regex for date check
 *
 * @param array $options Options which can override default settings, 
 * @return string Regex
 * @access public
 */
	function getCheckDateRegex($options = array()) {
		$settings = array_merge($this->_settings, (array)$options);
		
		$parts = array(
			'Y' => '([1-9][0-9]{0,3})',
			'M' => '((0[1-9])|(1[0-2]))',
			'D' => '((0[1-9])|([1-2][0-9])|(3[0-1]))'
		);
		$order = str_split($settings['dateFormat']);
		
		$regex = '^' . implode(
			'\\' . $settings['dateSeparator'],
			array($parts[$order[0]], $parts[$order[1]], $parts[$order[2]])
		) . '$';
		
		return $regex;
	}
/**
 * Checks that a value is a valid date.
 *
 * @param string $localDate Date in local foramt
 * @return boolean Success
 * @access public
 */
	function isValidDate($localDate, $options = array()) {
		return preg_match("/" . $this->getCheckDateRegex($options) . "/", $localDate);
	}
}